// 包声明，表明该类位于com.example.emos.wx.service.impl包下
package com.example.emos.wx.service.impl;

// 导入所需的类和库
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.example.emos.wx.config.SystemConstants;
import com.example.emos.wx.controller.form.CheckinForm;
import com.example.emos.wx.db.dao.TbCheckinDao;
import com.example.emos.wx.db.dao.TbFaceModelDao;
import com.example.emos.wx.db.dao.TbHolidaysDao;
import com.example.emos.wx.db.dao.TbWorkdayDao;
import com.example.emos.wx.db.pojo.TbCheckin;
import com.example.emos.wx.db.pojo.TbFaceModel;
import com.example.emos.wx.db.pojo.TbHolidays;
import com.example.emos.wx.exception.EmosException;
import com.example.emos.wx.service.CheckinService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;

// 使用Spring的@Service注解标记这个类为一个服务组件
@Service
// 使用Spring的@Scope注解将这个类的实例设置为prototype，即每次请求都会创建一个新的实例
@Scope("prototype")
// 使用Lombok的@Slf4j注解自动生成一个日志对象
@Slf4j
public class CheckinServiceImpl implements CheckinService {

	// 自动注入SystemConstants对象
	@Autowired
	private SystemConstants constants;

	// 自动注入TbHolidaysDao对象，用于处理节假日的数据访问
	@Autowired
	private TbHolidaysDao holidaysDao;

	// 自动注入TbWorkdayDao对象，用于处理工作日的数据访问
	@Autowired
	private TbWorkdayDao workdayDao;

	// 自动注入TbCheckinDao对象，用于处理考勤的数据访问
	@Autowired
	private TbCheckinDao checkinDao;

	// 5. 使用 @Autowired 注解自动注入 TbFaceModelDao
	@Autowired
	private TbFaceModelDao faceModelDao;

	// 7. 使用 @Value 注解读取配置文件中的 emos.face.checkinUrl 属性
	@Value("${emos.face.checkinUrl}")
	private String checkinUrl;

	@Value("${emos.face.createFaceModelUrl}")
	private String createFaceModelUrl;
	// 实现CheckinService接口中的validCanCheckIn方法
	@Override
	public String validCanCheckIn(int userId, String date) {
		// 检查今天是否是节假日
		boolean isTodayHoliday = holidaysDao.searchTodayIsHolidays() != null;
		// 检查今天是否是工作日
		boolean isTodayWorkday = workdayDao.searchTodayIsWorkday() != null;

		// 默认类型为工作日
		String type = "工作日";

		// 如果今天是周末，则类型为节假日
		if (DateUtil.date().isWeekend()) {
			type = "节假日";
		}

		// 如果今天是节假日，则类型为节假日
		if (isTodayHoliday) {
			type = "节假日";
		} else if (isTodayWorkday) { // 如果今天是工作日，则类型为工作日
			type = "工作日";
		}

		// 如果类型是节假日，则返回"节假日不需要考勤"
		if (type.equals("节假日")) {
			return "节假日不需要考勤";
		} else { // 如果类型是工作日，则继续检查考勤时间
			DateTime now = DateUtil.date();
			// 获取今天的考勤开始和结束时间
			String start = DateUtil.today() + " " + constants.attendanceStartTime;
			String end = DateUtil.today() + " " + constants.attendanceEndTime;

			DateTime attendanceStart = DateUtil.parse(start);
			DateTime attendanceEnd = DateUtil.parse(end);

			// 如果当前时间在考勤开始之前，则返回"没有到上班考勤开始时间"
			if (now.isBefore(attendanceStart)) {
				return "没有到上班考勤开始时间";
				// 如果当前时间在考勤结束之后，则返回"超过了上班考勤结束时间"
			} else if (now.isAfter(attendanceEnd)) {
				return "超过了上班考勤结束时间";
			} else { // 如果当前时间在考勤时间范围内，则检查是否已经考勤
				HashMap<String, Object> map = new HashMap<>();
				map.put("userId", userId);
				map.put("date", date);
				map.put("start", start);
				map.put("end", end);

				boolean hasCheckin = checkinDao.haveCheckin(map) != null;
				// 如果已经考勤，则返回"今日已经考勤，不用重复考勤"，否则返回"可以考勤"
				return hasCheckin ? "今日已经考勤，不用重复考勤" : "可以考勤";
			}
		}
	}

	@Override
	public void checkin(HashMap param){
		Date d1 = DateUtil.date(); // 当前时间
		Date d2 = DateUtil.parse(DateUtil.today() + " " + constants.attendanceStartTime); // 上班时间
		Date d3 = DateUtil.parse(DateUtil.today() + " " + constants.attendanceEndTime); // 签到结束时间

		int status = 1;
		if(d1.compareTo(d2) <= 0){
			status = 1; //正常打卡
		}else if(d1.compareTo(d2)>0 && d1.compareTo(d3) < 0){
			status = 2; //迟到
		}

//		查询人脸数据模型
		int userId= (Integer) param.get("userId");
		String faceModal = faceModelDao.searchFaceModel(userId);
//		如果存在人脸模型，抛出异常
		if(faceModal == null){
			throw new EmosException("不存在人脸模型");
		}else {
			// 27. 创建人脸识别请求
			String path=(String)param.get("path");
			// 28. 添加请求参数：照片和目标模型
			HttpRequest request = HttpUtil.createPost(checkinUrl);
			request.form("photo", FileUtil.file(path),"targrtModal",faceModal);
			HttpResponse response = request.execute();

			// 30. 判断请求状态，如果不是 200，抛出异常
			if(response.getStatus()!=200){
				log.error("人脸服务器异常");
				throw new EmosException("人脸服务器异常");
			}
			// 34. 获取请求返回的内容
			String body = response.body();

			if("无法识别出人脸".equals(body) || "照片中存在多张人脸".equals(body)){
				throw new EmosException(body);
			}else if("False".equals(body)){
				throw new EmosException("签到无效，非本人签到");
			}else if("True".equals(body)){
				// TODO 保存签到记录
				String city= (String) param.get("city");
				String district= (String) param.get("district");
				String address= (String) param.get("address");
				String country= (String) param.get("country");
				String province= (String) param.get("province");
				//保存签到记录
				TbCheckin entity = new TbCheckin();
				entity.setUserId(userId);
				entity.setAddress(address);
				entity.setCountry(country);
				entity.setProvince(province);
				entity.setCity(city);
				entity.setDistrict(district);
				entity.setStatus((byte) status);
				entity.setDate(DateUtil.today());
				entity.setCreateTime(d1);
				checkinDao.insert(entity);
			}
		}
	}

	@Override
	public void createFaceModal(int userId, String path) {
		// 创建 HTTP 请求
		HttpRequest request = HttpUtil.createPost(createFaceModelUrl);

		// 将照片作为表单提交
		request.form("photo", FileUtil.file(path));

		// 执行请求
		HttpResponse response = request.execute();

		// 获取响应体
		String body = response.body();

		// 处理响应
		if ("无法识别出人脸".equals(body) || "照片中存在多张人脸".equals(body)) {
			// 如果无法识别出人脸或照片中存在多张人脸，则抛出异常
			throw new EmosException(body);
		} else {
			// 否则，创建人脸模型实体并插入数据库
			TbFaceModel entity = new TbFaceModel();
			entity.setUserId(userId);
			entity.setFaceModel(body);
			faceModelDao.insert(entity);
		}
	}
}
